from collections import deque
from utils.basic_function import *


class RemovePseudoNodesTool(PreprocessingTool):
    def __init__(self, table, tolerance):
        super(RemovePseudoNodesTool, self).__init__(table)
        self.tolerance = tolerance

    def remove_pseudo_nodes_table(self):
        pk_list = self.table.get_pk_list()
        self.set_pk_list(deque(pk_list))
        self.remove_pseudo_nodes_workflow()

    def remove_pseudo_nodes_workflow(self):
        """
        搜索并处理伪结点
        """
        print("线段总数：", len(self.pk_list))
        count = 0
        while len(self.pk_list) != 0:
            pk = self.pk_list.popleft()
            print(pk)
            gdf = self.table.select_by_attr(self.table.pk, pk)
            geom = gdf[self.table.geom].iloc[0]
            st_coord = geom.coords[0]
            ed_coord = geom.coords[-1]
            intersect_pk_list = self.table.buffer_nodes(Point(st_coord), self.tolerance,
                                                        and_where=f"and {self.table.pk}!={pk}")[self.table.pk].values
            is_modified = self.remove_pesudo_nodes(pk, intersect_pk_list)
            if not is_modified:  # 如果在上一步对pk_self进行了修改，统一添加新的形状到队尾、删去数据库中的pk_self，下一步就不再进行了
                intersect_pk_list = self.table.buffer_nodes(Point(ed_coord), self.tolerance,
                                                            and_where=f"and {self.table.pk}!={pk}")[self.table.pk].values
                self.remove_pesudo_nodes(pk, intersect_pk_list)
            count += 1
            if count == 500:
                self.table.vacuum_analyze()
                count = 0

    def remove_pesudo_nodes(self, pk_self, intersect_pk_list, attr_dict=None):
        if len(intersect_pk_list) != 1:  # 不是伪结点
            is_modified = False
        else:
            pk_intersect = intersect_pk_list[0]
            print(f"self pk: {pk_self}, intersect pk: {pk_intersect}")
            geom_self = self.table.select_by_attr(self.table.pk, pk_self).loc[0, self.table.geom]
            geom_intersect = self.table.select_by_attr(self.table.pk, pk_intersect).loc[0, self.table.geom]
            # 不能合并环
            # 合并，返回合并后的geom和fun值
            geom_joined, fun_val = join(geom_self, geom_intersect)
            if is_same_point(geom_joined.coords[0], geom_joined.coords[-1]):
                return False
            # 更新合并结果
            try:
                # 事务开始
                with conn:
                    self.table.delete_by_attr(self.table.pk, pk_intersect)  # 删除原相交线段（数据库）
                    self.table.delete_by_attr(self.table.pk, pk_self)
                    if attr_dict:
                        attr_dict.update({self.table.geom: geom_joined})
                    else:
                        attr_dict = {self.table.geom: geom_joined}
                    pk_max = self.table.insert(attr_dict)
                # 事务正常结束
                is_modified = True  # 因为join后方向可能改变，继续处理endpoint可能导致遗漏
                self.pk_list.appendleft(pk_max)
            except GeomFixFailException:
                is_modified = False
                print(f"不能合并：{pk_self},{pk_intersect}")
            try:
                self.pk_list.remove(pk_intersect)  # 删除原相交线段
            except ValueError:
                pass
        return is_modified
